package com.rockcent.wechat.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.RBeanUtils;
import com.rockcent.common.utils.RDateFormatUtils;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.FavoriteType;
import com.rockcent.mall.lib.domain.enumclass.ProductEventType;
import com.rockcent.mall.lib.domain.enumclass.ProductStatus;
import com.rockcent.mall.lib.dto.*;
import com.rockcent.mall.lib.helper.ProductEventHelper;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.wechat.Routes;
import com.rockcent.wechat.helper.CustomerHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by zhangjh on 2016/10/22.
 * 用户个人信息相关接口
 */
@RestController
@RequestMapping(value = Routes.API_PREFIX)
public class CustomerController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(CustomerController.class);
    @Autowired
    private CustomerHelper customerHelper;
    @Autowired
    private FavoriteRepository favoriteRepository;
    @Autowired
    private ProductShareRepository productShareRepository;
    @Autowired
    private MerchantRepository merchantRepository;
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    private CustomerShoppingAddressRepository customerShoppingAddressRepository;
    @Autowired
    private LocationRepository locationRepository;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private MerchantProductRepository merchantProductRepository;
    @Autowired
    private ProductEventRepository productEventRepository;
    @Autowired
    private MerchantGiftPacketShareRepository merchantGiftPacketShareRepository;
    @Autowired
    private MerchantGiftPacketRepository merchantGiftPacketRepository;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MerchantStoreCustomerRepository merchantStoreCustomerRepository;
    @Autowired
    private MerchantStoreRepository merchantStoreRepository;
    @Autowired
    private ProductEventHelper productEventHelper;
    @Autowired
    private CustomerFundFlowRepository customerFundFlowRepository;
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * @api {get} /api/v2/customer/favorites/list 查询用户的收藏
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} domain <code>必须参数</code>对应平台C端域名
     * @apiHeader {String} userToken <code>必须参数</code>用户Token
     *
     * @apiParam {Integer} pageNo 页码
     * @apiParam {Integer} pageSize 每页记录数
     * @apiParam {String} favoriteType 收藏类型，PRODUCT 产品,MERCHANT 商铺
     *
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {String} type 类型 ALL("全部"), GOODS("商品"), SERVICE("服务")
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity 库存数量
     * @apiSuccess {BigDecimal} carriage 运费
     * @apiSuccess {String} dateEnabled 有效期开始时间
     * @apiSuccess {String} dateDisabled 有效期结束时间
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 商城 id
     * @apiSuccess {Long} merchantId 商家 id
     * @apiSuccess {String} merchantName 商家名称
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {Boolean} recommend 是否在分销市场展示
     * @apiSuccess {Integer} totalCount 总记录数
     * @apiSuccess {Integer} totalPage 总页数
     * @apiSuccess {Integer} pageNo 页码
     * @apiSuccess {Integer} pageSize 每页记录数
     *
     * @apiSuccessExample {json} 收藏的产品:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *              "data": [
     *                          {
     *                              "productList": [
     *                                                  {
     *                                                      "id": 10,
     *                                                      "dateCreated": "2016-05-11 11:04:31",
     *                                                      "lastUpdated": "2016-10-26 17:31:13",
     *                                                      "version": 3,
     *                                                      "marketId": 10,
     *                                                      "name": "假发",
     *                                                      "type": "GOODS",
     *                                                      "basePrice": 100,
     *                                                      "sellPrice": 86,
     *                                                      "quantity": 50,
     *                                                      "carriage": 0,
     *                                                      "refundable": false,
     *                                                      "sellnow": true,
     *                                                      "dateSelling": "2016-05-11 11:04:31",
     *                                                      "limitCount": 0,
     *                                                      "logoUrl": "/20160511/201605111104057YH6W1RK.jpg",
     *                                                      "note": "美",
     *                                                      "status": "SUPPLIER_CANCEL_SOLDOUT",
     *                                                      "mallId": 1,
     *                                                      "merchantId": 2,
     *                                                      "serveRate": "2.5",
     *                                                      "shippingType": "SHIPPING",
     *                                                      "resellFee": 10,
     *                                                      "shareFee": 0,
     *                                                      "marketPlatformType": "IN_PLATFORM"
     *                                                  },
     *                                                      ...
     *                                              ],
     *                                              "type": "PRODUCT"
     *                          }
     *                      ],
     *                      "totalCount": 4,
     *                      "totalPage": 1,
     *                      "pageNo": 0,
     *                      "pageSize": 100
     *          }
     *  }
     * @apiSuccessExample {json} 收藏的礼包:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *          "data": [
     *                      {
     *                          "merchantList": [
     *                                              {
     *                                                  "id": 2,
     *                                                  "dateCreated": "2016-05-05 17:55:37",
     *                                                  "lastUpdated": "2016-10-18 14:57:19",
     *                                                  "version": 23,
     *                                                  "name": "歌力思",
     *                                                  "email": "1123812664@qq.com",
     *                                                  "intro": "刘嘉玲携手歌力思集团年中狂欢全场0.8折起！刘嘉玲携手歌力思集团年中狂欢全场0.8折起！",
     *                                                  "status": "VERIFIED",
     *                                                  "userInfoId": 3,
     *                                                  "mallId": 1,
     *                                                  "salesCode": "B@PIuQXEGa",
     *                                                  "merchantRegisterType": "EMAIL",
     *                                                  "prodAudit": true
     *                                              },
     *                                               ...
     *                                          ],
     *                                           "type": "MERCHANT"
     *                      }
     *                  ],
     *                  "totalCount": 3,
     *                  "totalPage": 1,
     *                  "pageNo": 0,
     *                  "pageSize": 100
     *          }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_FAVORITES_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult listFavorite(Integer pageNo, Integer pageSize, String favoriteType, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (StringUtils.isBlank(favoriteType)) {
                jr.remind("favoriteType 不能为空",log);
                return;
            }
            if (pageNo == null && pageSize == null) {
                jr.remind("请输入分页条件",log);
                return;
            }
            //我的收藏默认查询收藏的产品
            FavoriteType type = FavoriteType.MERCHANT == FavoriteType.valueOf(favoriteType) ? FavoriteType.MERCHANT : FavoriteType.PRODUCT;

            PageResult<Favorite> favoritePageResult = favoriteRepository.findListFavorite(customerDto.getId(), type, this.getPage(pageNo, pageSize));
            FavoriteDto favoriteDto = new FavoriteDto();
            favoriteDto.setType(type);
            if (type  == FavoriteType.PRODUCT){
                List<Long> productIdList = favoritePageResult.data.stream().map(Favorite::getProductId).collect(Collectors.toList());
                List<Product> productList = merchantProductRepository.findByIdIn(productIdList);
                Map<Long,List<Product>> productMap = productList.stream().collect(Collectors.groupingBy(Product::getId));
                productList.clear();
                productIdList.stream().forEach(productId ->{
                    List<Product> temp = productMap.get(productId);
                    if (temp != null) {
                        productList.addAll(temp);
                    }
                });
                //补全信息：商家名称
                List<ProductDto> productDtoList =productList.stream().map(product -> {
                    ProductDto productDto = new ProductDto();
                    RBeanUtils.copyProperties(product,productDto);
                    Merchant merchant = merchantRepository.findOne(product.getMerchantId());
                    productDto.setMerchantName(merchant.getName());
                    //补全由于类型不同造成的信息不全
                    productDto.setType(product.getType().toString());
                    productDto.setType(product.getType().toString());
                    Double basePrice = product.getBasePrice() == null ? null : product.getBasePrice().doubleValue();
                    productDto.setBasePrice(basePrice);
                    productDto.setSellPrice(product.getSellPrice().doubleValue());
                    productDto.setCarriage(product.getCarriage().doubleValue());
                    productDto.setShippingType(product.getShippingType().toString());
                    productDto.setResellFee(product.getResellFee().doubleValue());
                    productDto.setShareFee(product.getShareFee().doubleValue());

                    return productDto;
                }).collect(Collectors.toList());
                favoriteDto.setProductList(productDtoList);
            }
            if (type == FavoriteType.MERCHANT){
                List<Long> merchantIdList = favoritePageResult.data.stream().map(Favorite::getMerchantId).collect(Collectors.toList());
                List<Merchant> merchantList = merchantRepository.findByIdIn(merchantIdList);
                Map<Long,List<Merchant>> merchantMap = merchantList.stream().collect(Collectors.groupingBy(Merchant::getId));
                merchantList.clear();
                merchantIdList.stream().forEach(merchantId ->{
                    List<Merchant> temp = merchantMap.get(merchantId);
                    if (temp != null) {
                        merchantList.addAll(temp);
                    }
                });
                favoriteDto.setMerchantList(merchantList);
            }
            PageResult<FavoriteDto> favoriteDtoPageResult = new PageResult<>();
            favoriteDtoPageResult.pageNo = favoritePageResult.pageNo;
            favoriteDtoPageResult.pageSize = favoritePageResult.pageSize;
            favoriteDtoPageResult.totalCount = favoritePageResult.totalCount;
            favoriteDtoPageResult.totalPage = favoritePageResult.totalPage;
            favoriteDtoPageResult.data.add(favoriteDto);
            jr.setData(favoriteDtoPageResult);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/favorites/add 添加用户的收藏
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} domain <code>必须参数</code>对应平台C端域名
     * @apiHeader {String} userToken <code>必须参数</code>用户Token
     *
     * @apiParam {String} favoriteType 收藏类型，PRODUCT 产品,MERCHANT 商铺
     * @apiParam {Long} targetId 目标Id，(无论是产品还是商品，都用该参数传值)
     *
     * @apiSuccess {Long} data 收藏的ID
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *      "code": "1",
     *      "desc": "成功",
     *      "data": 313
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_FAVORITES_ADD, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult addFavorite(String favoriteType,Long targetId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (favoriteType==null){
                jr.remind("请输入收藏类型",log);
                return;
            }
            if (targetId==null){
                jr.remind("请输入收藏的目标ID",log);
                return;
            }
            Favorite existFavorite =null;
            Favorite favorite = new Favorite();

            if (FavoriteType.PRODUCT.name().equals(favoriteType)) {
                //如果是产品
                Product product = merchantProductRepository.findByIdAndIsDeleteAndStatus(targetId,Whether.NO,ProductStatus.SELLING);
                if (product==null){
                    jr.errorParam("商品不存在或已下架",log);
                    return;
                }
                favorite.setProductId(targetId);
                favorite.setMerchantId(product.getMerchantId());
                existFavorite = favoriteRepository.findByCustomerIdAndProductIdAndType(customerDto.getId(),targetId,FavoriteType.PRODUCT);

            }else if (FavoriteType.MERCHANT.name().equals(favoriteType)){
                Merchant merchant = merchantRepository.findByIdAndMallId(targetId,customerDto.getMallId());
                if (merchant == null){
                    jr.errorParam("店铺不存在",log);
                    return;
                }
                //如果是商铺
                favorite.setMerchantId(targetId);
                existFavorite = favoriteRepository.findByCustomerIdAndMerchantIdAndType(customerDto.getId(),targetId,FavoriteType.MERCHANT);

            }else {
                jr.remind("请输入正确的收藏类型：PRODUCT 或 MERCHANT",log);
                return;
            }
            //如果收藏存在且类型一致
            if ( existFavorite!= null && existFavorite.getType().name().equalsIgnoreCase(favoriteType)){
                jr.remind("该"+FavoriteType.valueOf(favoriteType).getValue()+"已收藏",log);
                return;
            }
            favorite.setMallId(customerDto.getMallId());
            favorite.setCustomerId(customerDto.getId());
            favorite.setType(FavoriteType.valueOf(favoriteType));
            favorite.setIsDelete(Whether.NO);
            favorite.setDateCreated(new Date());
            favorite.setLastUpdated(new Date());
            favorite = favoriteRepository.save(favorite);
            jr.setData(favorite.getId());

        };
        return doing.go(request, log);
    }
    /**
     * @api {get} /api/v2/customer/favorites/delete 删除用户的收藏
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} domain <code>必须参数</code>对应平台C端域名
     * @apiHeader {String} userToken <code>必须参数</code>用户Token
     *
     * @apiParam {String} favoriteType 收藏类型，PRODUCT 产品,MERCHANT 商铺
     * @apiParam {Long} targetId 目标Id，(无论是产品还是商品，都用该参数传值)
     *
     * @apiSuccess {Long} data 收藏的ID
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *      "code": "1",
     *      "desc": "成功",
     *      "data": 313
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_FAVORITES_DELETE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult deleteFavorite(String favoriteType,Long targetId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (favoriteType==null){
                jr.remind("请输入收藏类型",log);
                return;
            }
            if (targetId==null){
                jr.remind("请输入收藏的目标ID",log);
                return;
            }
            Favorite existFavorite =null;

            if (FavoriteType.PRODUCT.name().equals(favoriteType)) {
                //如果是产品
                existFavorite = favoriteRepository.findByCustomerIdAndProductIdAndType(customerDto.getId(),targetId,FavoriteType.PRODUCT);

            }else if (FavoriteType.MERCHANT.name().equals(favoriteType)){
                //如果是商铺
                existFavorite = favoriteRepository.findByCustomerIdAndMerchantIdAndType(customerDto.getId(),targetId,FavoriteType.MERCHANT);

            }else {
                jr.remind("请输入正确的收藏类型：PRODUCT 或 MERCHANT",log);
                return;
            }
            //如果收藏存在且类型一致
            if ( existFavorite == null){
                jr.remind("该"+FavoriteType.valueOf(favoriteType).getValue()+"收藏已删除",log);
                return;
            }
            favoriteRepository.delete(existFavorite.getId());
            jr.setData(true);

        };
        return doing.go(request, log);
    }


    /**
     * @api {get} /api/v2/customer/my_shared_product 查看我分享的产品
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     * @apiParam {Integer} pageNo 页码
     * @apiParam {Integer} pageSize 每页记录数
     *
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {String} type 类型 ALL("全部"), GOODS("商品"), SERVICE("服务")
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity 库存数量
     * @apiSuccess {BigDecimal} carriage 运费
     * @apiSuccess {String} dateEnabled 有效期开始时间
     * @apiSuccess {String} dateDisabled 有效期结束时间
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 商城 id
     * @apiSuccess {Long} merchantId 商家 id
     * @apiSuccess {String} merchantName 商家名称
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {Boolean} recommend 是否在分销市场展示
     * @apiSuccess {Integer} totalCount 总记录数
     * @apiSuccess {Integer} totalPage 总页数
     * @apiSuccess {Integer} pageNo 页码
     * @apiSuccess {Integer} pageSize 每页记录数
     *
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *          "data": [
     *                      {
     *                      "id": 533,
     *                      "dateCreated": "2016-09-30 11:17:39",
     *                      "lastUpdated": "2016-10-09 11:00:08",
     *                      "type": "SERVICE",
     *                      "name": "黄金手链服务",
     *                      "basePrice": 100,
     *                      "sellPrice": 88,
     *                      "quantity": 983,
     *                      "carriage": 0,
     *                      "dateEnabled": "2016-09-30 00:00:00",
     *                      "dateDisabled": "2017-09-30 00:00:00",
     *                      "refundable": true,
     *                      "sellnow": true,
     *                      "dateSelling": "2016-09-30 11:17:39",
     *                      "limitCount": 0,
     *                      "logoUrl": "/20160930/201609301116306TFags5D.jpg",
     *                      "note": "黄金手链",
     *                      "status": "SELLING",
     *                      "mallId": 1,
     *                      "merchantId": 81,
     *                      "serveRate": "2.5",
     *                      "shippingType": "SHOP_PICKUP",
     *                      "resellFee": 3.65,
     *                      "shareFee": 2,
     *                      "merchantName": "国庆假宅家宅家",
     *                      "statusText": "在售"
     *                      },
     *                       ...
     *                  ],
     *                  "totalCount": 5,
     *                  "totalPage": 1,
     *                  "pageNo": 0,
     *                  "pageSize": 10
     *          }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_MY_SHARED_PRODUCT, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult getMySharedProduct(Integer pageNo, Integer pageSize, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (pageNo == null && pageSize == null) {
                jr.remind("请输入分页条件",log);
                return;
            }
            PageResult<ProductDto> productSharePage = productShareRepository.getCustomerShareList(customerDto.getId(), this.getPage(pageNo, pageSize));
            productSharePage.data.stream().forEach(productDto -> {
                Merchant merchant = merchantRepository.findOne(productDto.getMerchantId());
                if (merchant != null) {
                    productDto.setMerchantName(merchant.getName());
                }
            });
            jr.setData(productSharePage);
        };
        return doing.go(request, log);
    }
    /**
     * @api {get} /api/v2/customer/my_shared_gift_packet 查询我分享的礼包
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} userToken 用户Token
     * @apiHeader {String} domain 商城域名
     *
     * @apiParam {Integer} pageNo 页码
     * @apiParam {Integer} pageSize 每页记录数
     *
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {Long} marketId 分销礼包唯一的识别码
     * @apiSuccess {String} name 礼包标题
     * @apiSuccess {String} coverUrl 广告封面
     * @apiSuccess {Date} dateEnabled 出售开始时间
     * @apiSuccess {Date} dateDisabled 出售结束时间
     * @apiSuccess {String} intro 礼包介绍
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {BigDecimal} basePrice 总价
     * @apiSuccess {BigDecimal} sellPrice 礼包价
     * @apiSuccess {String} status 礼包状态 S1_DRAFTED("草稿"), S2_SELLING("已上架"), S3_UNLOAD("已下架"), S4_SOLDOUT("已售完"), S5_FINISHED("已结束")
     * @apiSuccess {Boolean} isRecommend 是否共享营销
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {Long} mallId 商城ID
     * @apiSuccess {String} merchantName 商家名称
     * @apiSuccess {String} resellFee 分销佣金
     * @apiSuccess {String} promoteUrl 产品礼包推广二维码图片路径
     *
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *  "data": [
     *              {
     *                  "id": 1,
     *                  "dateCreated": "2016-05-30 16:53:24",
     *                  "lastUpdated": "2016-11-07 13:48:41",
     *                  "version": 2,
     *                  "name": "礼包20160530165258",
     *                  "coverUrl": "/20160530/20160530165306Pjmy9LVL.png",
     *                  "dateEnabled": "2016-05-30 00:00:00",
     *                  "dateDisabled": "2016-06-29 00:00:00",
     *                  "intro": "礼包简介",
     *                  "shareFee": 0,
     *                  "basePrice": 100,
     *                  "sellPrice": 100,
     *                  "status": "S3_UNLOAD",
     *                  "merchantId": 2,
     *                  "mallId": 1,
     *                  "merchantName": "test1",
     *                  "resellFee": 0,
     *                  "recommend": false
     *              },
     *              ...
     *          ],
     *          "totalCount": 1,
     *          "totalPage": 1,
     *          "pageNo": 0,
     *          "pageSize": 10
     *      }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_MY_SHARED_GIFT_PACKET, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult getMySharedGiftPacket(Integer pageNo, Integer pageSize, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (pageNo == null && pageSize == null) {
                jr.remind("请输入分页条件",log);
                return;
            }
            List<MerchantGiftPacketShare> giftPacketShareList = merchantGiftPacketShareRepository.findGiftIdBySharedCustomerId(customerDto.getId());
            if (giftPacketShareList == null || giftPacketShareList.size() == 0 ){
                jr.remind("您还没有分享过",log);
                return;
            }
            List<Long> giftPacketIdList = giftPacketShareList.stream().map(MerchantGiftPacketShare::getGiftPacketId).collect(Collectors.toList());
            PageResult<MerchantGiftPacket> giftPacketPageResult =  merchantGiftPacketRepository.findByIdsPage( giftPacketIdList,this.getPage(pageNo,pageSize));

            jr.setData(giftPacketPageResult);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/customer/show 查询客户信息
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     *
     * @apiSuccess {Integer} id 用户ID
     * @apiSuccess {Integer} dateCreated 创建时间
     * @apiSuccess {Integer} lastUpdated 修改时间
     * @apiSuccess {Integer} version 版本
     * @apiSuccess {Integer} nickName 昵称
     * @apiSuccess {Integer} shareCode 分享码
     * @apiSuccess {Integer} status 状态 NORMAL("正常"), DISABLE("停用")
     * @apiSuccess {Integer} password 密码
     * @apiSuccess {Integer} mallId 平台ID
     * @apiSuccess {Integer} mobile 联系电话
     * @apiSuccess {Integer} wechatOpenId 绑定微信OpenId
     * @apiSuccess {Integer} wechatNickName 绑定微信昵称
     * @apiSuccess {Integer} wechatUnionId 绑定微信unionId
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *              "id": 93,
     *              "dateCreated": "2016-05-27 11:42:44",
     *              "lastUpdated": "2016-09-13 15:47:41",
     *              "version": 19,
     *              "password": "******",
     *              "nickName": "小周子",
     *              "shareCode": "C@v3CkvWRH",
     *              "status": "NORMAL",
     *              "mallId": 1
     *              "mobile": "12312312312"
     *          }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_SHOW, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult show(HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            //查询用户信息
            Customer customer = customerRepository.findOne(customerDto.getId());
            customer.setPassword("******");
            jr.setData(customer);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/address_create 增加收货地址（查询该用户是否有默认地址，如果没有设置当前地址为默认）
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     * @apiParam {Long} locationId 地区ID
     * @apiParam {String} address 地址
     * @apiParam {String} shoppingMan 收货人
     * @apiParam {Long} shoppingManPhone 收货人电话
     * @apiParam {String} [postcode] 邮政编码
     * @apiParam {String} default 是否默认收货地址 false 否 true 是，默认false
     *
     * @apiSuccess {Long} data 地址ID
     *
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": 183
     * }
     */
    @RequestMapping(value = Routes.CUSTOMER_ADDRESS_CREATE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult createShoppingAddress(CustomerShoppingAddress address, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (StringUtils.isBlank(address.getAddress())) {
                jr.remind("请输入收货地址",log);
                return;
            }
            if (StringUtils.isBlank(address.getShoppingMan())) {
                jr.remind("请输入收货人",log);
                return;
            }
            if (StringUtils.isBlank(address.getShoppingManPhone())) {
                jr.remind("收货人电话号码",log);
                return;
            }
            if (address.getLocationId() == null) {
                jr.remind("请选择地区",log);
                return;
            }
            if (address.getDefault() == null){
                jr.remind("请设置默认字段值",log);
                return;
            }
            if (!locationRepository.exists(address.getLocationId())) {
                jr.errorParam("该地区不存在",log);
                return;
            }
            address.setCustomerId(customerDto.getId());
            address.setDateCreated(new Date());
            address.setLastUpdated(new Date());
            //查询该用户是否有默认地址，如果没有设置当前地址为默认
            CustomerShoppingAddress isDefault =  customerShoppingAddressRepository.findByCustomerIdAndIsDefaultAndIsDelete(customerDto.getId(),Boolean.TRUE,Whether.NO);
            if (isDefault == null){
                //没有默认地址时，把当前的设为默认的（会发生在没有地址的情况）
                address.setDefault(Boolean.TRUE);
            }
            if (address.getDefault() && isDefault != null){
                isDefault.setDefault(Boolean.FALSE);
                customerShoppingAddressRepository.save(isDefault);
            }

            jr.setData(customerShoppingAddressRepository.save(address).getId());
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/address_update 修改收货地址
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} id 地址ID
     * @apiParam {Long} locationId 地区ID
     * @apiParam {String} address 地址
     * @apiParam {String} shoppingMan 收货人
     * @apiParam {Long} shoppingManPhone 收货人电话
     * @apiParam {String} [postcode] 邮政编码
     * @apiParam {String} default 是否默认收货地址 false 否 true 是，默认false
     *
     * @apiSuccess {Long} data 地址ID
     *
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": 183
     * }
     */
    @RequestMapping(value = Routes.CUSTOMER_ADDRESS_UPDATE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult updateShoppingAddress(CustomerShoppingAddress address, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (StringUtils.isBlank(address.getAddress())) {
                jr.remind("请输入收货地址",log);
                return;
            }
            if (StringUtils.isBlank(address.getShoppingMan())) {
                jr.remind("请输入收货人",log);
                return;
            }
            if (StringUtils.isBlank(address.getShoppingManPhone())) {
                jr.remind("收货人电话号码",log);
                return;
            }
            if (address.getLocationId() == null) {
                jr.remind("请选择地区",log);
                return;
            }
            if (address.getId() == null) {
                jr.remind("地址id不能为空",log);
                return;
            }
            if (address.getDefault() == null){
                jr.remind("请设置默认字段值",log);
                return;
            }
            if (!locationRepository.exists(address.getLocationId())) {
                jr.errorParam("该地区不存在",log);
                return;
            }
            CustomerShoppingAddress exiteAddress = customerShoppingAddressRepository.findOne(address.getId());
            if (exiteAddress == null) {
                jr.errorParam("该地址不存在",log);
                return;
            }
            //查询该用户是否有默认地址，如果没有设置当前地址为默认
            CustomerShoppingAddress isDefault =  customerShoppingAddressRepository.findByCustomerIdAndIsDefaultAndIsDelete(customerDto.getId(),Boolean.TRUE,Whether.NO);
            //如果当前修改的地址不是原来默认的地址，而又要设当前地址为默认的，要把原来的地址设为非默认的；如果当前地址是默认的，则不能设为非默认的
            if (address.getDefault() && isDefault != null  && !isDefault.getId().equals(exiteAddress.getId())){
                isDefault.setDefault(Boolean.FALSE);
                customerShoppingAddressRepository.save(isDefault);
                exiteAddress.setDefault(Boolean.TRUE);
            }else if (isDefault != null && isDefault.getId().equals(exiteAddress.getId())){
                exiteAddress.setDefault(Boolean.TRUE);
            }
            exiteAddress.setShoppingMan(address.getShoppingMan());
            exiteAddress.setShoppingManPhone(address.getShoppingManPhone());
            exiteAddress.setLocationId(address.getLocationId());
            exiteAddress.setPostcode(address.getPostcode());
            exiteAddress.setLastUpdated(new Date());
            exiteAddress.setAddress(address.getAddress());
            customerShoppingAddressRepository.save(exiteAddress);
            jr.setData(exiteAddress.getId());
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/customer/shopping_address 列表查询客户收货地址
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     *
     * @apiSuccess {Long} id 地址ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 地址ID
     * @apiSuccess {String} address 收货地址
     * @apiSuccess {String} shoppingMan 收货人
     * @apiSuccess {String} shoppingManPhone 收货人电话号码
     * @apiSuccess {Long} locationId 地区id
     * @apiSuccess {Long} customerId 客户id
     * @apiSuccess {Boolean} default 是否默认收货地址
     * @apiSuccess {String} postcode 邮政编码
     *
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": [
     *              {
     *                  "id": 176,
     *                  "dateCreated": "2016-10-10 13:49:51",
     *                  "lastUpdated": "2016-10-17 17:01:52",
     *                  "version": 13,
     *                  "address": "北京市市辖区东城区太和街无聊大院99号103",
     *                  "shoppingMan": "真实用户",
     *                  "shoppingManPhone": "13564758763",
     *                  "locationId": 110101,
     *                  "customerId": 93,
     *                  "default": true
     *              },
     *              ...
     *          ]
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_SHOPPING_ADDRESS, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult listShoppingAddress( HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            List<CustomerShoppingAddress> addressList = customerShoppingAddressRepository.findByCustomerId(customerDto.getId());
            List<CustomerShoppingAddress> longAddress = addressList.stream().map(customerShoppingAddress -> {
                LocationDto locationDto = locationRepository.findLongLocation(customerShoppingAddress.getLocationId());
                customerShoppingAddress.setAddress(locationDto.getLocationName() + customerShoppingAddress.getAddress());
                return customerShoppingAddress;
            }).collect(Collectors.toList());
            jr.setData(longAddress);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/customer/address 查询客户某个收货地址
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     *
     * @apiSuccess {Long} id 地址ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 地址ID
     * @apiSuccess {String} address 收货地址
     * @apiSuccess {String} shoppingMan 收货人
     * @apiSuccess {String} shoppingManPhone 收货人电话号码
     * @apiSuccess {Long} locationId 地区id
     * @apiSuccess {Long} locationName 地区id
     * @apiSuccess {Long} customerId 客户id
     * @apiSuccess {Boolean} default 是否默认收货地址
     * @apiSuccess {String} postcode 邮政编码
     *
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": [
     *              {
     *                  "id": 176,
     *                  "dateCreated": "2016-10-10 13:49:51",
     *                  "lastUpdated": "2016-10-17 17:01:52",
     *                  "version": 13,
     *                  "address": "北京市市辖区东城区太和街无聊大院99号103",
     *                  "shoppingMan": "真实用户",
     *                  "shoppingManPhone": "13564758763",
     *                  "locationId": 110101,
     *                  "locationName": "北京市市辖区东城区",
     *                  "customerId": 93,
     *                  "default": true
     *              },
     *          ]
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_ADDRESS, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult address(Long shoppingAddressId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (shoppingAddressId == null){
                jr.remind("shoppingAddressId is null",log);
                return;
            }
            CustomerShoppingAddress address = customerShoppingAddressRepository.findByIdAndCustomerId(shoppingAddressId,customerDto.getId());
            CustomerShoppingAddressDto addressDto = new CustomerShoppingAddressDto();
            RBeanUtils.copyProperties(address,addressDto);
            //查地区全称
            LocationDto locationDto = locationRepository.findLongLocation(address.getLocationId());
            addressDto.setLocationName(locationDto.getLocationName());
            jr.setData(addressDto);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/default_address 设置默认收货地址
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     * @apiParam {Long} shoppingAddressId 收货地址ID
     *
     * @apiSuccess {Long} Data 新默认地址ID
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": 16
     * }
     */
    @RequestMapping(value = Routes.CUSTOMER_DEFAULT_ADDRESS ,method= RequestMethod.POST)
    @ResponseBody
    public JsonResult setDefaultShoppingAddress(Long shoppingAddressId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            //检查
            if (shoppingAddressId==null){
                jr.remind("请输入需要设置的默认地址ID",log);
                return;
            }

            CustomerShoppingAddress defaultAddress = customerShoppingAddressRepository.findByCustomerIdAndIsDefaultAndIsDelete(customerDto.getId(),true, Whether.NO);
            if (defaultAddress != null && defaultAddress.getId().equals(shoppingAddressId)){
                jr.remind("无效操作，该地址已是默认地址",log);
                return;
            }
            if (defaultAddress != null) {
                //更改默认地址，原来的地址设为非默认
                defaultAddress.setDefault(false);
            }

            CustomerShoppingAddress newDefault = customerShoppingAddressRepository.findOne(shoppingAddressId);
            if (newDefault == null ){
                jr.errorParam("地址不存在",log);
                return;
            }
            //设新默认地址
            newDefault.setDefault(true);
            if (defaultAddress != null && customerShoppingAddressRepository.save(defaultAddress)==null){
                jr.errorParam("无效操作，请从新设置",log);
                return;
            }
            if (customerShoppingAddressRepository.save(newDefault)==null){
                jr.errorParam("无效操作，请从新设置",log);
                return;
            }
            jr.setData(newDefault.getId());
        };
        return doing.go(request, log);
    }
    /**
     * @api {post} /api/v2/customer/delete_address 删除收货地址
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     * @apiParam {Long} shoppingAddressId 收货地址ID
     *
     * @apiSuccess {Long} Data 成功返回true
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": true
     * }
     */
    @RequestMapping(value = Routes.CUSTOMER_DELETE_ADDRESS ,method= RequestMethod.POST)
    @ResponseBody
    public JsonResult deleteShoppingAddress(Long shoppingAddressId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (shoppingAddressId == null){
                jr.remind("shoppingAddressId:"+CustomerShoppingAddress.CHECK_ID_IS_NOT_NULL,log);
                return;
            }
            CustomerShoppingAddress customerShoppingAddress = customerShoppingAddressRepository.findOne(shoppingAddressId);
            if (customerShoppingAddress==null){
                jr.errorParam("操作无效，此记录已删除或不存在",log);
                return;
            }
            if (!customerDto.getId().equals(customerShoppingAddress.getCustomerId())){
                jr.errorParam("操作无效，此记录已删除或不存在",log);
                return;
            }
            customerShoppingAddressRepository.delete(customerShoppingAddress);
            //查看是否默认，如果不是默认直接删除，如果是默认的，删除后新设一个默认地址
            if (customerShoppingAddress.getDefault()){
                List<CustomerShoppingAddress> address = customerShoppingAddressRepository.findByCustomerId(customerDto.getId());
                if(address.size() > 0){
                    CustomerShoppingAddress defaultAddress =  address.get(0);
                    defaultAddress.setDefault(Boolean.TRUE);
                    customerShoppingAddressRepository.save(defaultAddress);
                }
            }

            jr.setData(true);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/customer/product_list 查询产品清单
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} userToken 用户Token
     * @apiHeader {String} domain 对应平台C端域名
     *
     * @apiParam {String} productIdList 产品ID，需要写成数组形式：[1,2,3,...]
     * @apiParam {Integer} pageNo 页码
     * @apiParam {Integer} pageSize 每页记录数
     *
     * @apiSuccess {Long} merchantId 商铺ID
     * @apiSuccess {Long} merchantName 商铺名称
     * @apiSuccess {List} productList 商铺下的产品列表
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity  库存数量
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} logoUrls 多LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {String} favourite 是否已收藏，YES:已收藏，NO:未收藏
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": [
     *              {
     *                  "merchantId": 2,
     *                  "merchantName": "歌力思",
     *                  "productList": [
     *                                      {
     *                                          "id": 1,
     *                                          "dateCreated": "2016-05-05 18:24:34",
     *                                          "lastUpdated": "2016-05-05 18:24:34",
     *                                          "version": 1,
     *                                          "name": "口红",
     *                                          "type": "GOODS",
     *                                          "basePrice": 100,
     *                                          "sellPrice": 0.2,
     *                                          "quantity": 50,
     *                                          "carriage": 0,
     *                                          "refundable": false,
     *                                          "sellnow": true,
     *                                          "dateSelling": "2016-05-05 18:18:35",
     *                                          "limitCount": 0,
     *                                          "logoUrl": "/20160505/20160505181744MOXrxYK6.jpg",
     *                                          "note": "口红，遇水不褪色",
     *                                          "status": "SOLDOUT",
     *                                          "mallId": 1,
     *                                          "merchantId": 2,
     *                                          "serveRate": "2.5",
     *                                          "shippingType": "SHIPPING",
     *                                          "resellFee": 0.05,
     *                                          "shareFee": 0.04
     *                                      },
     *                                       ...
     *                                  ]
     *                  },
     *                  ...
     *          ]
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_PRODCUT_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult orderProductList(String productIdList,Integer pageNo ,Integer pageSize, HttpServletRequest request) {
        RestDoing doing = jr ->{
            if (productIdList==null){
                jr.remind("productIdList 参数不能为空",log);
                return;
            }
            if (pageNo==null && pageSize == null){
                jr.remind("请输入分页条件",log);
                return;
            }
            List<Long> ids = objectMapper.readValue(productIdList,new TypeReference<List<Long>>() {});
            PageResult<Merchant> merchantPageResult = merchantProductRepository.getOrderProductMerchant(ids,  this.getPage(pageNo,pageSize));
            List<ShoppingCartDto> orderProductList = merchantPageResult.data.stream().map(merchant ->{
                ShoppingCartDto productList = new ShoppingCartDto();
                productList.setMerchantName(merchant.getName());
                productList.setMerchantId(merchant.getId());

                productList.setProductList( merchantProductRepository.findByMerchantIdAndIdIn(merchant.getId(),ids));
                return productList;
            }).collect(Collectors.toList());
            PageResult pageResult = this.getPage(pageNo,pageSize);
            pageResult.totalPage = merchantPageResult.totalPage;
            pageResult.totalCount = merchantPageResult.totalCount;
            pageResult.data = orderProductList;
            jr.setData(pageResult);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/customer/shared_summary_month 查看一个月的分享统计
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} userToken 用户Token
     * @apiHeader {String} domain 对应平台C端域名
     *
     * @apiParam {String} statisticSum 分享总收入
     * @apiParam {Integer} clickCount 每月点击量
     * @apiParam {Integer} saleCount 每月销售量
     * @apiParam {Integer} verificationCount 每月核销量
     * @apiParam {BigDecimal} monthlyIncome 每月分享收入
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *              "statisticSum": "15",
     *              "clickCount": 1,
     *              "saleCount": 1,
     *              "verificationCount": 1,
     *              "monthlyIncome": 3
     *          }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_SHARED_SUMMARY_MONTH, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult sharedSummaryMonth(HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr ->{
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            //将小时至0
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            //将分钟至0
            calendar.set(Calendar.MINUTE, 0);
            //将秒至0
            calendar.set(Calendar.SECOND,0);
            //将毫秒至0
            calendar.set(Calendar.MILLISECOND, 0);
            //获得当前月第一天
            String firstDate = RDateFormatUtils.format(calendar.getTime());
            //将当前月加1；
            calendar.add(Calendar.MONTH, 1);
            //在当前月的下一月基础上减去1毫秒
            calendar.add(Calendar.MILLISECOND, -1);
            //获得当前月最后一天
            String lastDate = RDateFormatUtils.format(calendar.getTime());
            //查询记录
            List<ProductEvent> productEventList = productEventRepository.findBySharerIdAndDateCreatedBetween(customerDto.getId(),firstDate,lastDate);
            //用户分享总收入
            StatisticDto statisticDto =  customerFundFlowRepository.findStatisticSum(customerDto.getId());
            //分享月收入
            Double monthlyIncome = customerFundFlowRepository.findMonthlyIncome(customerDto.getId(),firstDate,lastDate);
            //修复monthlyIncome为NULL引起的问题
            monthlyIncome = monthlyIncome==null?new Double(0):monthlyIncome;
            statisticDto.setMonthlyIncome(BigDecimal.valueOf(monthlyIncome));

            if (statisticDto == null ||productEventList==null ){
                jr.errorParam("用户未有分享记录",log);
                return;
            }
            if (StringUtils.isBlank(statisticDto.getStatisticSum())){
                statisticDto.setStatisticSum("0");
            }
            //统计
            for (ProductEvent productEvent:productEventList){
                if (productEvent.getEventType()==ProductEventType.CLICKED){
                    statisticDto.setClickCount(statisticDto.getClickCount()+1);
                }
                if (productEvent.getEventType()==ProductEventType.SALED){
                    statisticDto.setSaleCount(statisticDto.getSaleCount()+1);
                }
                if (productEvent.getEventType()==ProductEventType.VERIFIED){
                    statisticDto.setVerificationCount(statisticDto.getVerificationCount()+1);
                }
            }


            jr.setData(statisticDto);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/sharing_product 用户分享产品
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} userToken 用户Token
     * @apiHeader {String} domain 对应平台C端域名
     *
     * @apiParam {List} ids 分享ID,例如"ids":[969,970,971]
     *
     * @apiParamExample {json} 输入参数格式
     * {
     *  "ids":[969,967,980]
     *  }
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": true
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.CUSTOMER_SHARING_PRODUCT, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult sharingProduct(@RequestBody ProductDto productDto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr ->{
            //商品验证
            if (productDto.getIds() == null || productDto.getIds().size() <= 0 ){
                jr.remind("productId:"+Product.CHECK_ID_IS_NOT_NULL,log);
                return;
            }
            List<Product> productList = merchantProductRepository.findByIdInAndMallIdAndIsDelete(productDto.getIds(),customerDto.getMallId(),Whether.NO);
            if (productList == null || productList.size() <=0 || productDto.getIds().size() != productList.size() ){
                jr.errorParam("某商品不存在",log);
                return;
            }
            //如果已经加入了分享表，不需要重新执行保存操作，直接返回
            List<ProductShare> productShareList = productShareRepository.findBySharedCustomerIdAndProductIdIn(customerDto.getId(),productDto.getIds());
            List myShare = null;
            if (productShareList != null && productShareList.size() > 0 ) {
                //更新分享时间
                productShareList.stream().forEach(productShare -> {
                    productShare.setLastUpdated(new Date());
                });
                myShare = productShareRepository.save(productShareList);
            }
            //不重复插入分享数据
            List<Long> productShareIdList = productShareList.stream().map(ProductShare::getProductId).collect(Collectors.toList());
            //过滤：把没有分享过的产品过滤出来
            List<Product> productList1 = productList.stream().filter(product -> !productShareIdList.contains(product.getId())).collect(Collectors.toList());

            if (productList1 !=null && productList1.size() >0 ) {
                //保存之前还没有分享过的商品
                Customer customer = customerRepository.findOne(customerDto.getId());
                List<ProductShare> productShares = new ArrayList<>();
                productList1.stream().forEach(product -> {
                    ProductShare productShare = new ProductShare();
                    productShare.setProductId(product.getId());
                    productShare.setSharedCustomerId(customer.getId());
                    productShare.setShareCode(customer.getShareCode());
                    productShare.setDateCreated(new Date());
                    productShare.setLastUpdated(productShare.getDateCreated());
                    productShare.setIsDelete(Whether.NO);
                    productShares.add(productShare);
                });
                myShare = productShareRepository.save(productShares);
            }
            if (myShare == null || myShare.size() <= 0) {
                jr.errorParam("分享失败",log);
                return;
            }


            //记录产品event
            ProductEventDto productEventDto = new ProductEventDto();
            productEventDto.setEventType(ProductEventType.SHARED);
            productEventDto.setCustomerId(customerDto.getId());
            productEventDto.setCustomerName(customerDto.getNickName());
            productEventHelper.view(productList,productEventDto);

            jr.setData(true);
        };
        return doing.go(request, log);
    }
    /**
     * @api {post} /api/v2/customer/sharing_gift_packet 用户分享礼包
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} userToken 用户Token
     * @apiHeader {String} domain 对应平台C端域名
     *
     * @apiParam {Long} giftPacketId 礼包Id
     *
     * @apiSuccess {String} id 分享ID
     * @apiSuccess {Integer} dateCreated 创建时间
     * @apiSuccess {Integer} lastUpdated 更新时间
     * @apiSuccess {Integer} version 版本
     * @apiSuccess {BigDecimal} giftPacketId 礼包ID
     * @apiSuccess {BigDecimal} shareCode 用户分享码
     * @apiSuccess {BigDecimal} sharedCustomerId 分享用户ID
     *
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *              "id": 2,
     *              "dateCreated": "2016-11-04 18:59:50",
     *              "lastUpdated": "2016-11-04 18:59:50",
     *              "version": 0,
     *              "giftPacketId": 1,
     *              "shareCode": "C@UBonXnQ7",
     *              "sharedCustomerId": 239
     *          }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_SHARING_GIFT_PACKET, method = RequestMethod.POST)
    public JsonResult sharingGiftPacket(Long giftPacketId,HttpServletRequest request){
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            //礼包验证
            if (giftPacketId==null){
                jr.remind("giftPacketId:"+ MerchantGiftPacket.CHECK_ID_IS_NOT_NULL,log);
                return;
            }
            MerchantGiftPacket merchantGiftPacket = merchantGiftPacketRepository.findOne(giftPacketId);
            //商品需要与用户处在同一平台下，并且未逻辑删除
            if (merchantGiftPacket==null || merchantGiftPacket.getMallId()!=customerDto.getMallId() || merchantGiftPacket.getIsDelete() != Whether.NO){
                jr.errorParam("分享失败：此礼包不存在或不能分享",log);
                return;
            }
            //如果已经加入了分享表，不需要重新执行保存操作，直接返回
            MerchantGiftPacketShare merchantGiftPacketShare = merchantGiftPacketShareRepository.findBySharedCustomerIdAndGiftPacketId(customerDto.getId(),giftPacketId);
            if (merchantGiftPacketShare!=null){
                jr.setData(merchantGiftPacketShare);
                return;
            }
            //保存
            Customer customer = customerRepository.findOne(customerDto.getId());
            merchantGiftPacketShare = new MerchantGiftPacketShare();
            merchantGiftPacketShare.setGiftPacketId(giftPacketId);
            merchantGiftPacketShare.setSharedCustomerId(customer.getId());
            merchantGiftPacketShare.setShareCode(customer.getShareCode());
            merchantGiftPacketShare.setDateCreated(new Date());
            merchantGiftPacketShare.setLastUpdated(merchantGiftPacketShare.getDateCreated());
            merchantGiftPacketShare.setIsDelete(Whether.NO);
            jr.setData(merchantGiftPacketShareRepository.save(merchantGiftPacketShare));
        };
        return doing.go(request, log);
    }

    /*先不做，检查客户购买产品数量的限制
    @RequestMapping(value = Routes.CUSTOMER_CHECK_PRODUCT_LIMIT, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult checkProductLimit(Long productId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr ->{
            if (productId==null){
                jr.remind("商品ID:"+Product.CHECK_ID_IS_NOT_NULL,log);;
                return;
            }
            Product product = merchantProductRepository.findOne(productId);
            //不会出现限购数量为0的情况
            if (product==null || product.getLimitCount()<=0){
                jr.errorParam("商品不存在");
                return;
            }
            Integer buyCount = 0;
            ShoppingCart shoppingCart = shoppingCartRepository.findByCustomerIdAndProductId(customerDto.getId(),productId);
            if (shoppingCart!=null){
                buyCount = shoppingCart.getBuyCount();
            }
            customerProductLimitRepository.


            Customer customer = customerRepository.findOne(customerDto.getId());

        };
        return doing.go(request, log);
    }*/

    /**
     * @api {put} /api/v2/customer/belong/store/verifier 绑定核销员
     * @apiGroup customer
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {Long} storeId <code>必须参数</code> 门店ID
     * @apiParam {Long} verifyPersonId <code>必须参数</code> 核销员ID
     * @apiParam {String} wechatOpenId <code>必须参数</code> openId
     * @apiParam {String} verifyKey <code>必须参数</code> 验证码
     * @apiParam {Long} merchantId <code>必须参数</code> 商家ID
     *
     * @apiSuccess {String} code 1:代表成功, 3:代表温馨提示, 5:代表核销员工不存在
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功"
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.CUSTOMER_BELONG_STORE_VERIFIER, method = RequestMethod.PUT)
    public JsonResult saveMerchantStoreCustomer(HttpServletRequest request, @RequestBody MerchantStoreCustomerDto dto){
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getStoreId() == null) {
                jsonResult.remind("门店ID 不能为空",log);
                return;
            }

            if (dto.getVerifyPersonId() == null) {
                jsonResult.remind("核销员ID 不能为空",log);
                return;
            }

            if (dto.getVerifyKey() == null) {
                jsonResult.remind("验证码 不能为空",log);
                return;
            }

            if (dto.getWechatOpenId() == null) {
                jsonResult.remind("openId 不能为空",log);
                return;
            }

            Customer customer = customerRepository.findByIdAndWechatOpenIdAndIsDelete(dto.getVerifyPersonId(), dto.getWechatOpenId(), Whether.NO);
            if (customer == null) {
                jsonResult.custom("5", "不是本站成员,不能绑定成为核销员", log);
                return;
            }

            MerchantStore merchantStore = merchantStoreRepository.findByIdAndMerchantIdAndMallIdAndIsDelete(dto.getStoreId(), dto.getMerchantId(), customerDto.getMallId(), Whether.NO);
            if (merchantStore == null) {
                jsonResult.custom("5", "门店不存在,请联系工作人员", log);
                return;
            }

            Merchant merchant = merchantRepository.findByIdAndMallId(dto.getMerchantId(), customerDto.getMallId());
            if (merchant == null) {
                jsonResult.custom("5", "商家不存在,请联系工作人员", log);
                return;
            }

            String merchantId = stringRedisTemplate.opsForValue().get(dto.getVerifyKey());
            if (StringUtils.isBlank(merchantId)) {
                jsonResult.custom("5", "此二维码已经失效", log);
                return;
            }
            if (!Objects.equals(merchant.getId(), Long.valueOf(merchantId))) {
                jsonResult.custom("5", "此二维码无效", log);
                return;
            }

            MerchantStoreCustomer storeCustomer = merchantStoreCustomerRepository.findByVerifyPersonIdAndMerchantIdAndIsDelete(dto.getVerifyPersonId(), merchant.getId(), Whether.NO);
            if (storeCustomer != null) {
                jsonResult.custom("6", "一个微信号只能绑定一次", log);
                return;
            }

            storeCustomer = new MerchantStoreCustomer();
            storeCustomer.setNickName(customer.getNickName());
            storeCustomer.setStoreId(dto.getStoreId());
            storeCustomer.setVerifyPersonId(dto.getVerifyPersonId());
            storeCustomer.setMerchantId(merchant.getId());
            merchantStoreCustomerRepository.save(storeCustomer);
        };
        return doing.go(request, log);
    }



    /**
     * @api {get} /api/v2/customer/validate_code 验证码用户手机
     * @apiGroup customer
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} phoneNum 验证电话号码
     * @apiParam {String} captchaTemp 客户手机收到验证码
     * @apiParam {boolean} protocol 协议签订
     * @apiParam {String} source 来源，WXAPP:微信小程序；WEXIN:公众号H5
     *
     * @apiSuccessExample {json} Success-Response:
     * HTTP/1.1 200 OK
     *{
     *   "code": "1",
     *   "desc": "成功",
     *   "data": false
     *}
     *
     */
    @RequestMapping(value = Routes.CUSTOMER_VALIDATE_CODE, method = RequestMethod.GET)
    public JsonResult validateCode(String phoneNum, String captchaTemp, boolean protocol, String source, HttpServletRequest request, HttpServletResponse response) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            Long customerDtoId = customerDto.getId();
            Customer customer = customerRepository.findOne(customerDtoId);
//            if (StringUtils.isNotBlank(customer.getMobile())){
//                jr.errorParam("该账户已经绑定过手机号");
//                return;
//            }
            if (StringUtils.isBlank(phoneNum)) {
                jr.errorParam("phoneNum is null",log);
                return;
            }
            if (StringUtils.isBlank(captchaTemp)) {
                jr.errorParam("captchaTemp is null",log);
                return;
            }
            if (protocol == false) {
                jr.errorParam("protocol can not false",log);
                return;
            }
            Long mallId = customerDto.getMallId();

//            if (mobileCustomer != null){
//                jr.errorParam("该手机号已经被绑定过了");
//                return;
//            }
            Map<String, String> data = new HashMap<>();

            //验证码的校验
            boolean result = false;
            Object oCaptcha = redisTemplate.opsForValue().get(customerDtoId +":"+phoneNum);
            if (null != oCaptcha && String.valueOf(oCaptcha).equals(captchaTemp)) {
                Customer mobileCustomer = customerRepository.findByMobileAndMallId(phoneNum, mallId);
                //如果没有手机号码存在系统中，忽略新创建的用户id
                if (mobileCustomer != null){
                    result = true;
                    if("WXAPP".equals(source)){
                        mobileCustomer.setWxappOpenId(customer.getWxappOpenId());
                    }else if("WEXIN".equals(source)){
                        mobileCustomer.setWechatOpenId(customer.getWechatOpenId());
                    }
                    customerRepository.save(mobileCustomer);
                    //刷新前端token
                    CustomerDto customerSession = customerHelper.setSession(mobileCustomer, request, response);
                    log.info("======================>customerSession{}" , customerSession);
                    String sessionId = customerSession.getUserToken();

                    data.put("sessionId", sessionId);
                    data.put("mobile", phoneNum);

                    //产出新创建用户信息
                    customer.setIsDelete(Whether.YES);
                    customerRepository.save(customer);
                }else{
                    customer.setMobile(phoneNum);
                    customer.setProtocol(Whether.YES);
                    customer.setIsDelete(Whether.YES);
                    customerRepository.save(customer);
                }

                //每个验证码只能用一次
                redisTemplate.delete(customerDtoId +":"+phoneNum);
                jr.data = data;
            }
//            jr.setData(result);
        };
        return doing.go(request, log);
    }

}
